package rebol.eclipse.plugin.helpers;

import java.beans.XMLDecoder;
import java.beans.XMLEncoder;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

//http://www.cise.ufl.edu/~amyles/tcpchat/

class Server extends Thread {

	// /server

	static int socketId = 1234;

	Service service;

	abstract static class Service {
		abstract public Object process(Object[] request);
	}

	public void run() {
		try {
			ServerSocket srvr = new ServerSocket(socketId);
			while (true) {
				request(srvr);
			}
			// srvr.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private void request(ServerSocket srvr) throws IOException {
		Socket skt = srvr.accept();
		Log.s("Connection");
		String data = read(skt);
		XMLDecoder xd = new XMLDecoder(
				new ByteArrayInputStream(data.getBytes()));
		Object[] in = (Object[]) xd.readObject();
		xd.close();
		Log.s(data);
		Object res = service.process(in);
		PrintWriter out = new PrintWriter(skt.getOutputStream(), true);
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		XMLEncoder xe = new XMLEncoder(bos);
		xe.writeObject(res);
		xe.close();
		data = bos.toString();
		Log.s("Reply: " + data);
		out.print(data);
		out.close();
		skt.close();
	}

	private String read(Socket skt) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(skt
				.getInputStream()));
		int len;
		try {
			len = Integer.parseInt(br.readLine());
		} catch (NumberFormatException e) {
			len = 0;
			e.printStackTrace();
		}
		Log.s(len);
		StringBuffer dataBuf = new StringBuffer();
		while (len > dataBuf.length()) {
			String nw = br.readLine();
			dataBuf.append(nw);
			dataBuf.append('\n');
		}
		return dataBuf.toString();
	}

	// test

	public static void callRebolClient() {
		Rebol.printConfig();
		Object[] res = (Object[]) Rebol.call(new File(Config.scriptDir,
				"test-server.r"), "called-by-java", new Object[] { "server",
				socketId }, true);
		Log.s(res[0]);
		Log.s(res[1]);

	}

	public static void main(String args[]) {
		Server sv = new Server();
		sv.setDaemon(true);
		sv.service = new Server.Service() {

			@Override
			public Object process(Object[] request) {
				return new Object[] { "Service-got",
						new Object[] { request[0], request[1] } };
			}

		};

		sv.start();
		callRebolClient();
	}
}
